package com.cgm.common;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

/**
 * 日期工具类
 */
public class DateUtil {

	private static int FIRST_DATE_OF_WEEK = Calendar.SUNDAY;
	public static final int BEFORE_START_DATE = -2;// 一个日期早于一个日期区间
	public static final int EQUAL_START_DATE = -1;// 一个日期等于一个日期区间的开始日期
	public static final int BETWEEN_TOW_DATE = 0;// 一个日期在一个日期区间之内
	public static final int EQUAL_END_DATE = 1;// 一个日期等于一个日期区间的结束日期
	public static final int AFTER_END_DATE = 2;// 一个日期晚于一个日期区间
	public static final int TREE_DATE_EQUAL = 3;// 三个日期相等
	// 普通日期格式
	public static final String NORMAL_DATE_PATTERN = "yyyy-MM-dd";
	public static final String ZHCN_DATE_PATTERN = "yyyy年MM月dd日";
	public static final String ZHCN_DATE_TIME_PATTERN = "yyyy年MM月dd日 HH:mm:ss";
	public static final String NORMAL_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";

	/**
	 * Formats a Date into a date/time string.
	 * 
	 * @param date
	 * @param pattern
	 *            格式 yyyyMMddHHmmss / yyMMdd /...
	 * @return
	 */
	public static String format(Date date, String pattern) {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	/**
	 * Parses text from the beginning of the given string to produce a date.
	 * 
	 * @param date
	 *            日期字符串
	 * @param pattern
	 *            格式 yyyyMMddHHmmss / yyMMdd /...
	 * @return
	 * @throws ParseException
	 */
	public static Date parse(String date, String pattern) {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		try {
			Date d = sdf.parse(date);
			return d;
		} catch (ParseException e) {
			throw new RuntimeException("日期转换错误", e);
		}

	}

	/**
	 * add(Calendar.DAY_OF_MONTH, -5)
	 * 
	 * @param date
	 * @param calendorField
	 * @param amount
	 * @return
	 */
	public static Date add(Date date, int calendorField, int amount) {
		Calendar cal = Calendar.getInstance();

		cal.setTime(date);

		cal.add(calendorField, amount);

		return cal.getTime();
	}

	/**
	 * @return Calendar.SUNDAY <br/>
	 *         Calendar.MONDAY <br/>
	 *         Calendar.TUESDAY <br/>
	 *         Calendar.WEDNESDAY <br/>
	 *         Calendar.THURSDAY <br/>
	 *         Calendar.FRIDAY <br/>
	 *         Calendar.SATURDAY <br/>
	 */
	public static int getDayOfWeek(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		switch (cal.get(Calendar.DAY_OF_WEEK)) {
		case 1:
			return 7;
		case 2:
			return 1;
		case 3:
			return 2;
		case 4:
			return 3;
		case 5:
			return 4;
		case 6:
			return 5;
		default:
			return 6;
		}
	}

	/**
	 * @return Calendar.SUNDAY <br/>
	 *         Calendar.MONDAY <br/>
	 *         Calendar.TUESDAY <br/>
	 *         Calendar.WEDNESDAY <br/>
	 *         Calendar.THURSDAY <br/>
	 *         Calendar.FRIDAY <br/>
	 *         Calendar.SATURDAY <br/>
	 */
	public static int getDayOfMouth(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.DAY_OF_MONTH);
	}

	/**
	 * 计算两个日期间相差的天数
	 * 
	 * @param date
	 * @param compareDate
	 * @return
	 * @throws ParseException
	 */
	public static long compareTo(Date date, Date compareDate) {
		// 去掉时分秒
		date = parse(format(date, "yyMMdd"), "yyMMdd");
		compareDate = parse(format(compareDate, "yyMMdd"), "yyMMdd");

		long a = (date.getTime() - compareDate.getTime())
				/ (1000 * 60 * 60 * 24);
		return a;
	}

	/**
	 * 判断是否为一周的最后一天(目前配置的是周日为一周的第一天)
	 * 
	 * @param date
	 * @return
	 */
	public static boolean isEndOfWeek(Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DAY_OF_MONTH, 1);
		int weekDay = cal.get(Calendar.DAY_OF_WEEK);
		if (weekDay == FIRST_DATE_OF_WEEK) {
			return true;
		}
		return false;
	}

	/**
	 * 判断时间是否为月末
	 * 
	 * @param nowDate
	 *            日期（需要验证的日期）
	 * @return boolean true 表示是月末 false 表示不为月末
	 * */
	public static boolean isMonthEnd(Date nowDate) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(nowDate);
		cal.add(Calendar.DAY_OF_MONTH, 1);
		int day = cal.get(Calendar.DAY_OF_MONTH);
		if (day == 1) {
			return true;
		}
		return false;
	}

	/**
	 * 判断时间是否为季末
	 * 
	 * @param nowDate
	 *            日期（需要验证的日期）
	 * @return boolean true 表示是季末 false 表示不是季末
	 */
	public static boolean isQuarterEnd(Date nowDate) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(nowDate);
		int month = cal.get(Calendar.MONTH);
		cal.add(Calendar.DAY_OF_MONTH, 1);
		int day = cal.get(Calendar.DAY_OF_MONTH);
		if (day == 1
				&& (month == Calendar.MARCH || month == Calendar.JUNE
						|| month == Calendar.SEPTEMBER || month == Calendar.DECEMBER)) {
			return true;
		}
		return false;
	}

	/**
	 * 判断时间是否为季出
	 * 
	 * @param nowDate
	 *            日期（需要验证的日期）
	 * @return boolean true 表示是季初 false 表示不是季初
	 */
	public static boolean isQuarterBegin(Date nowDate) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(nowDate);
		int month = cal.get(Calendar.MONTH);
		int day = cal.get(Calendar.DAY_OF_MONTH);
		if (day == 1
				&& (month == Calendar.JANUARY || month == Calendar.APRIL
						|| month == Calendar.JULY || month == Calendar.OCTOBER)) {
			return true;
		}
		return false;
	}

	/**
	 * 判断时间是否为半年末
	 * 
	 * @param nowDate
	 *            日期（需要验证的日期）
	 * @return boolean true 表示是半年末 false 表示不是半年末
	 */
	public static boolean isHalfYearEnd(Date nowDate) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(nowDate);
		int month = cal.get(Calendar.MONTH);
		cal.add(Calendar.DAY_OF_MONTH, 1);
		int day = cal.get(Calendar.DAY_OF_MONTH);
		if (day == 1 && (month == Calendar.JUNE || month == Calendar.DECEMBER)) {
			return true;
		}
		return false;
	}

	/**
	 * 判断时间是否为半年出
	 * 
	 * @param nowDate
	 *            日期（需要验证的日期）
	 * @return boolean true 表示是半年初 false 表示不是半年初
	 */
	public static boolean isHalfYearBegin(Date nowDate) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(nowDate);
		int month = cal.get(Calendar.MONTH);
		int day = cal.get(Calendar.DAY_OF_MONTH);
		if (day == 1 && (month == Calendar.JANUARY || month == Calendar.JULY)) {
			return true;
		}
		return false;
	}

	/**
	 * 判断时间是否为年末
	 * 
	 * @param nowDate
	 *            日期（需要验证的日期）
	 * @return boolean true 表示是年末 false 表示不为年末
	 */
	public static boolean isYearEnd(Date nowDate) {
		if ("1231".equals(format(nowDate, "MMdd"))) {
			return true;
		}
		return false;
	}

	/**
	 * 判断时间是否为年初
	 * 
	 * @param nowDate
	 *            日期（需要验证的日期）
	 * @return boolean true 表示是年初 false 表示不为年初
	 */
	public static boolean isYearBegin(Date nowDate) {
		if ("0101".equals(format(nowDate, "MMdd"))) {
			return true;
		}
		return false;
	}

	/**
	 * 获取日期的年月日

	 * @return
	 */
	public static Calendar getYMD(Date date) {
		String dateStr = format(date, "yyyyMMdd");
		date = parse(dateStr, "yyyyMMdd");
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar;
	}

	/**
	 * 判断是否为结算日期
	 * 
	 * @param stlCycle
	 *            ,stlCycleDay,tranDate
	 * @return boolean
	 */
	public static boolean chkStlTime(String stlCycle, String stlCycleDay,
			Date tranDate) {
		boolean b = false;
		switch (stlCycle.toCharArray()[0]) {
		case '1':
			// 日结
			b = true;
			break;
		case '2':
			// 周结
			String nowDate = String.valueOf(DateUtil.getDayOfWeek(tranDate));
			if (nowDate.equals(stlCycleDay)) {
				b = true;
			}
			break;
		case '3':
			// 月结
			if (stlCycleDay.equals("0")) {
				// 月末结
				boolean result = DateUtil.isMonthEnd(tranDate);
				if (result) {
					b = true;
				}
			} else {
				// 非月末结
				String nowDate1 = String.valueOf(DateUtil
						.getDayOfMouth(tranDate));
				if (nowDate1.equals(stlCycleDay)) {
					b = true;
				}
			}
			break;
		case '4':
			// 季结
			if ("1".equals(stlCycleDay)) {
				// 季初
				if (DateUtil.isQuarterBegin(tranDate)) {
					b = true;
				}
			} else if ("0".equals(stlCycleDay)) {
				// 季末
				if (DateUtil.isQuarterEnd(tranDate)) {
					b = true;
				}
			}
			break;
		case '5':
			// 半年结
			if ("1".equals(stlCycleDay)) {
				// 半年初
				if (DateUtil.isHalfYearBegin(tranDate)) {
					b = true;
				}
			} else if ("0".equals(stlCycleDay)) {
				// 半年末
				if (DateUtil.isHalfYearEnd(tranDate)) {
					b = true;
				}
			}
			break;
		case '6':
			// 年结
			if ("1".equals(stlCycleDay)) {
				// 年初
				if (DateUtil.isYearBegin(tranDate)) {
					b = true;
				}
			} else if ("0".equals(stlCycleDay)) {
				// 年末
				if (DateUtil.isYearEnd(tranDate)) {
					b = true;
				}
			}
			break;
		default:
			break;
		}
		return b;
	}

	// 比较频繁交易前后两笔的时间间隔与指定的某个时间对比，在这个时间段内，是频繁交易
	public static boolean monFreCompare(Date startTime, Date endTime,
			int interTime) {
		boolean flag = false;
		long a = (endTime.getTime() - startTime.getTime());
		// 两笔交易的时间间隔<=interTime,是频繁交易
		long interval = a / 1000;
		if (interval <= interTime && interval > 0) {
			flag = true;
		}

		return flag;
	}

	private DateUtil() {
	}

	/**
	 * 描述: 判断<firstDate>时间点是否在<secondDate>时间点之前 如果此 firstDate
	 * 的时间在参数<secondDate>表示的时间之前，则返回小于 0 的值
	 * 
	 * @author chenlc
	 * @param firstDate
	 * @param secondDate
	 * @return
	 */
	public static boolean isBefore(Date firstDate, Date secondDate) {
		return compare(firstDate, secondDate) < 0 ? true : false;
	}

	/**
	 * 描述: 判断<firstDate>时间点是否在<secondDate>时间点之后 如果此 firstDate
	 * 的时间在参数<secondDate>表示的时间之后，则返回大于 0 的值
	 * 
	 * @author chenlc
	 * @param firstDate
	 * @param secondDate
	 * @return
	 */
	public static boolean isAfter(Date firstDate, Date secondDate) {
		return compare(firstDate, secondDate) > 0 ? true : false;
	}

	/**
	 * 描述: 比较两个时间点是否相等
	 * 
	 * @author chenlc
	 * @param firstDate
	 * @param secondDate
	 * @return
	 */
	public static boolean isEqual(Date firstDate, Date secondDate) {
		return compare(firstDate, secondDate) == 0 ? true : false;
	}

	/**
	 * 描述: 比较两个时间点 如果secondDate表示的时间等于此 firstDate 表示的时间，则返回 0 值； 如果此 firstDate
	 * 的时间在参数<secondDate>表示的时间之前，则返回小于 0 的值； 如果此 firstDate
	 * 的时间在参数<secondDate>表示的时间之后，则返回大于 0 的值
	 * 
	 * @author chenlc
	 * @param firstDate
	 * @param secondDate
	 * @return
	 */
	public static int compare(Date firstDate, Date secondDate) {
		Calendar firstCalendar = null;
		if (firstDate != null) {
			firstCalendar = Calendar.getInstance();
			firstCalendar.setTime(firstDate);
		}
		Calendar secondCalendar = null;
		if (firstDate != null) {
			secondCalendar = Calendar.getInstance();
			secondCalendar.setTime(secondDate);
		}
		try {
			return firstCalendar.compareTo(secondCalendar);
		} catch (NullPointerException e) {
			throw new IllegalArgumentException(e);
		} catch (IllegalArgumentException e) {
			throw new IllegalArgumentException(e);
		}
	}

	/**
	 * 描述: 时间区间判断
	 * 
	 * @author chenlc
	 * @param startDate
	 * @param endDate
	 * @param inDate
	 * @return
	 */
	public static int betweenTowDate(Date startDate, Date endDate, Date inDate) {
		if (isBefore(endDate, startDate)) {
			throw new IllegalArgumentException(
					"endDate can not before startDate!");
		}
		int sflag = compare(inDate, startDate);
		int eflag = compare(inDate, endDate);
		int flag = 0;
		if (sflag < 0) {
			flag = DateUtil.BEFORE_START_DATE;
		} else if (sflag == 0) {
			if (eflag == 0) {
				flag = DateUtil.TREE_DATE_EQUAL;
			} else {
				flag = DateUtil.EQUAL_START_DATE;
			}
		} else if (sflag > 0 && eflag < 0) {
			flag = DateUtil.BETWEEN_TOW_DATE;
		} else if (eflag == 0) {
			flag = DateUtil.EQUAL_END_DATE;
		} else if (eflag > 0) {
			flag = DateUtil.AFTER_END_DATE;
		}
		return flag;
	}

	/**
	 * 描述: 分别判断当前日期是与一个日期区间的六种情况比较 （1） 一个日期早于一个日期区间 （2）三个日期相等
	 * （3）一个日期等于一个日期区间的开始日期 （4）一个日期在一个日期区间之内 （5）一个日期等于一个日期区间的结束日期
	 * （6）一个日期晚于一个日期区间
	 * 
	 * @author chenlc
	 * @param startDate
	 * @param endDate
	 * @return
	 */
	public static int betweenTowDate(Date startDate, Date endDate) {
		return betweenTowDate(startDate, endDate, new Date());
	}

	/**
	 *
	 * @param startDate 日期
	 * @param x 小时
	 * @return
	 */
	public static String addDate(String startDate, int x)
	{
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//24小时制
		Date date = null;
		try
		{
			date = format.parse(startDate);
		}
		catch (Exception ex)
		{
			ex.printStackTrace();
		}
		if (date == null) return "";
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, x);//24小时制
		date = cal.getTime();
		cal = null;
		return format.format(date);
	}

	public static void main(String[] args) {
		String startTime = "2017-02-20 9:40:12";
        String add = DateUtil.addDate(startTime,24*7);
		System.out.println("add:{}"+add);
		Date startDate = DateUtil.parse(add,NORMAL_DATETIME_PATTERN);

		int count = DateUtil.compare(startDate,new Date());
		System.out.println(count);
		while (count < 0){
			add =  DateUtil.addDate(add,24*7);

			if (DateUtil.compare(DateUtil.parse(add,NORMAL_DATETIME_PATTERN),new Date()) > 0) {
              break;
			}

		}
		System.out.println("add2：{}"+add);
	}

}
